home *** CD-ROM | disk | FTP | other *** search
- /* The boo and de-boo programs do not work, and I found them too cumbersome
- * and complicated to install on the DG. In their place, I have provided
- * a few other tools:
- *
- * uuencode ansd uudecode:
- * Convert any binary file to a non-binary file, and preserve the
- * DG record and file types, if done on DG systems.
- * sq and usq:
- * CP/M (and others) squeeze and unsqueeze programs. Should be
- * compatible with Unix and other hosts.
- * compress:
- * a more efficient compression than sq/usq. Also compatible with
- * many hosts.
- *
- * If anyone can get these other files working, more power to you. The
- * uudecode program is slow, but the squeeze programs are very fast. The
- * uudecode could be faster, but I did not want to wasted alot of time on
- * it. Anyway, the uudecode source is very simple, and should be easy to
- * convert to another language. If you do convert the uudecode program,
- * please let me know, so that it can be distributed to hosts that do not
- * have the C compiler.
- *
- * Phil Julian, SAS Institute, Inc., Box 8000, Cary, NC 27512-8000
- *
- */
-
- /* MSBMKB.C
- *
- * Update history:
- *
- * Modified 3/11/86 Howie Kaye -- Columbia University
- * added UNIX and Microsoft C compatibility
- * changed I/O to be buffered
- * note: there is a bug built into the EOF handling which causes the
- * output file to grow everytime a file is packed/unpacked. This is
- * because 2 nulls and a space are added at the end of each run. As
- * the data is past the end of the file, it does not affect the program
- * produced.
- *
- * [1] Version adapted from the DEC-20 code to run on Lattice-C (v 2.14)
- * on an IBM PC/AT under DOS 3.0. Alan Phillips, Lancaster University UK
- *
- * Original by Bill Catchings, Columbia University, July 1984
- */
-
- /*
- * This program takes a file and encodes it into printable characters.
- * These printable files can then be decoded by the programs MSPCBOOT.BAS
- * or MSPCTRAN.BAS as the need may be. The file is encoded by taking
- * three consecutive eight bit bytes and dividing them into four six bit
- * bytes. An ASCII zero was then added to the resulting four characters.
- * to make them all printable ASCII characters in the range of the
- * character zero to the character underscore. In order to reduce the
- * size of the file null repeat count was used. The null repeat count
- * compresses up to 78 consecutive nulls into only two characters. This
- * is done by using the character tilde (~) as an indication that a group
- * of repetitive nulls has occured. The character following the tilde is
- * number of nulls in the group. The number is also converted in to a
- * printable character by adding an ASCII zero. The highest number of
- * nulls is therefore the highest printable character tilde. This is
- * equal to tilde minus zero nulls or 78 nulls. Because of the three
- * byte to four byte encoding the repeat counting can only start with
- * the first character of a three byte triplet.
- *
- * This C program was written specifically for the DEC-20 and as such
- * will not easily be transported to another system. The main problem
- * lies in the file I/O routines. It is necessary to make sure that
- * untranslated eight bit bytes are input from the input file. The
- * main change would be to make the OPEN statement reflect this for
- * your particular system and brand of UNIX and C. The rest of the
- * program should be transportable with little or no problems.
- */
-
- /*
- * set msdos if to be compiled on an msdos machine
- */
-
- #define MSDOS 0
- #define UNIX 0
- #define TOPS20 0
-
- #include <stdio.h> /* Standard UNIX i/o definitions */
-
- #if MSDOS /* [1] */
- #include <fcntl.h>
- #endif
- #if UNIX
- #include <sys/file.h>
- #endif /* [1] */
- #if TOPS20
- #include <file.h>
- #endif
- /* Datageneral is already defined */
- #ifdef datageneral
- #include <sys_calls.h>
- #include <packets/filestatus.h> /* Used for ?GNFN */
- #include <packets:normal_io.h>
- #include <paru.h>
- struct p_nio_ex w_io_parms; /* ?write system call structure */
- struct p_nio_ex r_io_parms; /* ?read system call structure */
- P_FSTAT buf;
- int ac0,ac2;
- char name[256];
- #define R_ACC 4
- #ifdef putc
- #undef putc
- #endif
- #define putc(c,file) { char ch = (char) (c); dg_binw(fchannel(file),&ch,1); }
- #define write(filen,chs,len) dg_binw(channel(filen),chs,len)
- #define read(filen,chs,len) dg_binr(channel(filen),chs,len)
- #endif
-
- /* Symbol Definitions */
-
- #define MAXPACK 80 /* Maximum packet size */
-
- #define MYRPTQ '~' /* Repeat count prefix I will use */
- #define DATALEN 78 /* Length of data buffer */
-
- #define TRUE -1 /* Boolean constants */
- #define FALSE 0
-
- /* Macros */
-
- #define tochar(ch) ((ch) + '0')
-
- /* Global Variables */
-
- int maxsize, /* Max size for data field */
- fd, /* File pointer of file to read/write */
- ofd,
- #if !(MSDOS | UNIX) /* [1] */
- nc, /* Count of input characters */
- oc, /* Count of output characters */
- otot, /* What char number we are processing */
- #endif
- rpt, /* repeat count */
- rptq, /* repeat quote */
- rptflg, /* repeat processing flag */
- size, /* size of present data */
- #if (MSDOS|UNIX|datageneral) /* [1] */
- t, /* Current character value as 16 bit */
- #endif /* [1] */
- eoflag; /* Set when file is empty. */
-
- #if (MSDOS|UNIX) /* [1] */
- long nc, /* Count of input characters */
- oc, /* Number of output chars */
- otot; /* What char number we are processing */
- #endif /* [1] */
-
- char one,
- two,
- three,
- #if !(MSDOS|UNIX|datageneral) /* [1] */
- t, /* Current character */
- #endif /* [1] */
- *filnam, /* Current file name */
- *ofile,
- packet[MAXPACK]; /* Packet buffer */
-
- main(argc,argv) /* Main program */
- int argc; /* Command line argument count */
- char **argv; /* Pointers to args */
- {
- char sfile(); /* Send file routine & ret code */
- #ifdef datageneral
- /* Initialize the i/o block for putc() */
- zero((char *) &w_io_parms, sizeof(w_io_parms));
- w_io_parms.isti = $IBIN|$RTDY|$ICRF|$OFOT;
- w_io_parms.isti &= ~$IPST;
- w_io_parms.imrs = 2048;
- w_io_parms.ibad = -1;
- w_io_parms.ircl = -1;
-
- zero((char *) &r_io_parms, sizeof(r_io_parms));
- r_io_parms.isti = $IBIN|$RTDY|$ICRF|$OFIN;
- r_io_parms.isti &= ~$IPST;
- r_io_parms.imrs = 2048;
- r_io_parms.ibad = -1;
- r_io_parms.ircl = -1;
-
- #endif
- if (--argc != 2) usage(); /* Make sure there's a command line. */
- rptq = MYRPTQ; /* Repeat Quote */
- rptflg = TRUE; /* Repeat Count Processing Flag */
-
- filnam = *++argv; /* Get file to send */
- ofile = *++argv; /* Output file to create */
- sfile();
- #if (MSDOS|UNIX) /* [1] */
- printf("Done, in: %ld, out: %ld, efficiency: %.2f%%\n",nc,oc,(100.0*nc)/oc);
- #else
- printf("Done, in: %d, out: %d, efficiency: %.2f%%\n",nc,oc,(100.0*nc)/oc);
- #endif /* [1] */
- }
-
- /*
- S F I L E - Send a whole file
- */
-
- char sfile() /* Send a file */
- {
- char *i;
-
- #if MSDOS /* [1] */
- #ifndef O_RAW
- #define O_RAW O_BINARY
- #endif O_RAW
- #endif MSDOS
- #if UNIX
- #define O_RAW 0
- #endif UNIX
- #ifdef datageneral
- FILE *temp1,*temp2;
- /* temp1 = fopen(filnam,"j"); */
- temp1 = dg_open(filnam,$OFIN|$IBIN|$ICRF|$RTDY,$FUNX);
- if (temp1 == NULL) fd = -1;
- else fd = fileno(temp1);
- #else
- #if (MSDOS | UNIX)
- fd = open(filnam,O_RDONLY | O_RAW,0x1ff);
- #else
- fd = open(filnam,FATT_RDONLY | FATT_BINARY | FATT_DEFSIZE,0x1ff);
- #endif /* [1] */
- #endif /* [1] */
- if (fd < 0) /* Report any errors */
- {
- printf("\n?Error opening file \"%s\"\n",filnam);
- exit(1);
- }
-
- #ifdef datageneral
- temp2 = dg_open(ofile,$OFOT|$IBIN|$OFCR|$OFCE|$RTDY,$FUDF);
- if (temp2 == NULL) ofd = -1;
- else ofd = fileno(temp2);
- #else
- #if (MSDOS | UNIX)
- ofd = open(ofile,O_CREAT|O_WRONLY|O_TRUNC|O_RAW,0x1ff);
- #else
- ofd = open(ofile,FATT_WRONLY | FATT_CREATE | FATT_BINARY,0x1ff);
- #endif /* [1] */
- #endif /* [1] */
-
- if (ofd < 0)
- {
- printf("\n?error opening file \"%s\"\n",ofile);
- exit(1);
- }
-
- oc = strlen(filnam); /* Get the string length. */
- for (i=filnam; *i != '\0'; i++) /* Uppercase the file name. */
- if (*i >= 'a' && *i <= 'z') *i ^= 040;
- write(ofd,filnam,oc); /* Write the file name in the file. */
- #if (!UNIX && !datageneral)
- write(ofd,"\r\n",2);
- #else
- write(ofd,"\n",1);
- #endif
- maxsize = DATALEN - 5;
- rpt = 0; /* Zero the repeat count. */
- oc = nc = 0; /* Output & input character counts. */
- otot = 1; /* Start with first char of triplet. */
- while (getbuf() > 0) /* While not EOF, get a packet. */
- {
- #if (!UNIX && !datageneral)
- packet[size++] = '\r'; /* Explicit CRLF. */
- #endif
- packet[size++] = '\n';
- packet[size] = '\0';
- oc += size; /* Count output size. */
- write(ofd,packet,size); /* Write the packet to the file. */
- /* printf("%d: %s",size,packet);*/ /* Print on the screen for testing. */
- }
- #if (MSDOS|datageneral) /* [1] */
- close(fd); /* close the files neatly */
- close(ofd);
- #endif /* [1] */
- }
- /*
- G E T B U F -- Do one packet.
- */
-
- getbuf() /* Fill one packet buffer. */
- {
- if (eoflag != 0) return(-1); /* If at the end of file, stop. */
- size = 0;
- while((t = getch()) >= 0) /* t == -1 means EOF. */
- {
- nc++; /* Count the character. */
- process(t); /* Process the character. */
- if (size >= maxsize) /* If the packet is full, */
- {
- packet[size] = '\0'; /* terminate the string. */
- return(size);
- }
- }
- eoflag = -1; /* Say we hit the end of the file. */
- process(0); /* Clean out any remaining chars. */
- process(0);
- process(' ');
- packet[size] = '\0'; /* Return any partial final buffer. */
- return(size);
- }
-
- /* P R O C E S S -- Do one character. */
-
- process(a)
- char a;
- {
- if (otot == 1) /* Is this the first of three chars? */
- {
- if (a == 0) /* Is it a null? */
- {
- if (++rpt < 78) /* Below max nulls, just count. */
- return;
- else if (rpt == 78) /* Reached max number, must output. */
- {
- packet[size++] = rptq; /* Put in null repeat char and */
- packet[size++] = tochar(rpt); /* number of nulls. */
- packet[size] = '\0';
- rpt = 0;
- return;
- }
- }
- else
- {
- if (rpt == 1) /* Just one null? */
- {
- one = 0; /* Say the first char was a null. */
- two = a; /* This char is the second one. */
- otot = 3; /* Look for the third char. */
- rpt = 0; /* Restart null count. */
- return;
- }
- if (rpt > 1) /* Some number of nulls? */
- {
- packet[size++] = rptq; /* Insert the repeat prefix */
- packet[size++] = tochar(rpt); /* and count. */
- packet[size] = '\0';
- rpt = 0; /* Reset repeat counter. */
- }
- one = a; /* Set first character. */
- otot = 2; /* Say we are at the second char. */
- }
- }
- else if (otot == 2)
- {
- two = a; /* Set second character. */
- otot = 3; /* Say we are at the third char. */
- }
- else
- {
- three = a;
- otot = 1; /* Start over at one. */
- pack(one,two,three); /* Pack in the three characters. */
- }
- }
-
- /* This routine does the actual three character to four character encoding.
- * The concept is relatively straight forward. The first output character
- * consists of the first (high order or most significant) six bits of the
- * first input character. The second output character is made from the
- * remaining two low order bits of the first input character and the first
- * four high order bits of the second input character. The third output
- * character is built from the last four low order bits of the second input
- * character and the two high order bits of the third input character. The
- * fourth and last output character consists of the six low order bit of
- * the third input character. In this way the three eight bit input char-
- * acters (for a total of 24 bits) are divided into four six bit output
- * characters (also for a total of 24 bits). In order to make the four
- * output characters printable an ASCII zero is then added to each of them.
- *
- */
-
- pack(x,y,z)
- char x,y,z;
- {
- packet[size++] = tochar((x >> 2) & 077);
- packet[size++] = tochar(((x & 003) << 4) | ((y >> 4) & 017));
- packet[size++] = tochar(((y & 017) << 2) | ((z >> 6) & 003));
- packet[size++] = tochar(z & 077);
- packet[size] = '\0';
- }
-
- int
- getch() /* Get next (or pushed) char. */
- {
- #if TOPS20
- /* really really inefficient. */
- return((read(fd,&a,1) > 0) ? (int) (a&0xff) : -1); /* (or -1 if EOF) */
- #else
- #ifndef BSIZE
- #define BSIZE 500
- #endif
- static int index = 0, count = 0;
- static char buf[BSIZE];
-
- if (count == 0) {
- count = read(fd,buf,BSIZE);
- if (count <= 0) return(-1);
- index = 0;
- }
- count--;
- return(buf[index++]&0xff);
-
- #endif
- }
-
- usage() /* Give message if user makes */
- { /* a mistake in the command. */
- fprintf(stderr,"usage: msmkboo inputfile outputfile\n");
- exit(1);
- }
-
- #ifdef datageneral
- /* D G _ B I N W -- Output len characters to the file number filenum
- *
- * The syntax is like the Unix write command.
- * This code was borrowed from my Kermit source -- ckdtio.c
- */
-
- dg_binw(channel,chs,len) int channel, len; char *chs;
- {
- int ac2,err;
-
- if (len == 0) return(0);
-
- w_io_parms.ich = channel;
- w_io_parms.ibad = chs;
- w_io_parms.ircl = len;
- ac2 = &w_io_parms;
-
- if ((err = sys_write(ac2)) == 0) return(0);
-
- if ( err != ERLTL && err != EREOF ) {
- perror("dg_binw: sys_write ");
- exit(err);
- }
- }
-
- /* D G _ B I N R -- Binary input routine
- *
- * The syntax is like the Unix read command.
- * This code was borrowed from my Kermit source -- ckdtio.c
- */
-
- dg_binr(channel,chs,len) int channel, len; char *chs;
- {
- int ac2, /* I/O parameter address block */
- err, /* Error from sys_read */
- irlr; /* Number of bytes read */
-
- r_io_parms.ich = channel;
- r_io_parms.ibad = chs;
- r_io_parms.ircl = len;
- ac2 = &r_io_parms;
- err = sys_read(ac2);
- irlr = r_io_parms.irlr;
- if (err == 0) return(irlr);
-
- if ((err != ERLTL) && (err != EREOF)) {
- /* NOT line-too-long, or EOF errors. */
- perror("dg_binr: sys_read ");
- return(-err);
- } else if (err == EREOF) return(-1); /* EOF */
- }
- #endif datageneral
-
-
-